package com.fausto.learnimprint.message.producer

import com.fausto.learnimprint.log.Slf4j.Companion.log
import com.fausto.learnimprint.log.controller.ControllerLog
import com.fausto.learnimprint.message.MqConstant
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Pointcut
import org.springframework.amqp.rabbit.core.RabbitTemplate
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import java.util.*
import javax.servlet.http.HttpServletRequest

@Aspect
@Component
class ControllerLogProducer {
    @Autowired
    lateinit var request: HttpServletRequest

    @Autowired
    lateinit var rabbitTemplate: RabbitTemplate


    companion object {
        /**
         * 不打印日志的路径
         */
        private val PASS_PATH: MutableSet<String> = HashSet(2)

        init {
            PASS_PATH.add("/user/getMailSendState")
            PASS_PATH.add("/log/findNewestLog")
        }
    }

    /**
     * 拦截控制层的所有public方法
     */
    @Pointcut("execution(public * com.fausto.learnimprint.core.controller.*.*(..))")
    fun log() {
    }

    /**
     * 方法执行前后 拦截
     *
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("log()")
    @Throws(Throwable::class)
    fun around(pjp: ProceedingJoinPoint): Any{

        val requestUri: String = request.requestURI

        //方法消耗时间
        val start = System.currentTimeMillis()
        val obj = pjp.proceed()
        val end = System.currentTimeMillis()

        val value = obj.toString()
        val time = end - start

        if (!PASS_PATH.contains(requestUri)) {
            val logInfo = "\n{" +
                    "\n\tURL:[" + requestUri + "]," +
                    "\n\tRequestMethod:[" + request.method + "]," +
                    "\n\tArgs:" + Arrays.toString(pjp.args) + "," +
                    "\n\tReturnValue:[" + value + "]," +
                    "\n\tTime:[" + time + "ms]," +
                    "\n\tMethodName:[" + pjp.signature + "]" +
                    "\n}"

            log.info(logInfo)

            try {
                val controllerLog = ControllerLog().apply {
                    url = requestUri
                    requestMethod = request.method
                    args = Arrays.toString(pjp.args)
                    returnValue = value
                    this.time = time.toInt()
                    methodName = pjp.signature.toString()
                    date = Date()
                }

                rabbitTemplate.convertAndSend(MqConstant.CONTROLLER_LOG_QUEUE, controllerLog)

            } catch (t: Throwable) {
                log.error("日志消息发送失败", t)
            }
        }
        return obj
    }
}